﻿using System;
using System.CodeDom.Compiler;
using DhbInterfaces;
using EmbeddedSharp.Core;
using Microsoft.CSharp;

namespace EmbeddedSharp.Scripting.Algebra
{
    public class OneVariableFunctionCompiler
    {
        private readonly IFunctionManager funcMgr;
        private readonly CompilerParameters m_CompilerParameters;
        private readonly CodeDomProvider m_Provider;

        public OneVariableFunctionCompiler()
        {
            // Create the compiler
            m_Provider = new CSharpCodeProvider();
            // Set the parameters of the compiler
            m_CompilerParameters = new CompilerParameters(
                new[]
                    {
                        "System.dll",
                        "DhbInterfaces.dll",
                        GetType().Assembly.Location
                    });
            m_CompilerParameters.GenerateInMemory = true;
            m_CompilerParameters.GenerateExecutable = false;
        }

        public OneVariableFunctionCompiler(IFunctionManager funcMgr)
            : this()
        {
            this.funcMgr = funcMgr;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="root"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public IOneVariableFunction Parse(Node root, string param)
        {
            var uft
                = new UnaryFunctionTranslator(
                    funcMgr, param);
            string fexpr = uft.Translate(root);

            var compiler =
                new OneVariableFunctionCompiler();

            IOneVariableFunction func = compiler.Parse(fexpr);

            return func;
        }

        public IOneVariableFunction Parse(string expr)
        {
            //CheckExpression(ref expr);
            string src =
                "using System;using DhbInterfaces;"
                + "class MyFunctionClass : IOneVariableFunction"
                + "{" + "public MyFunctionClass(){}" + "public double Value(double x)"
                + "{" + "return " + expr + ";" + "}" + "}";

            CompilerResults results = m_Provider.CompileAssemblyFromSource(
                m_CompilerParameters, src);
            Console.WriteLine(src);
            if (results.Errors.Count == 0 && results.CompiledAssembly != null)
            {
                Type ObjType = results.CompiledAssembly.GetType("MyFunctionClass");
                IOneVariableFunction func = null;

                if (ObjType != null)
                {
                    func = Activator.CreateInstance(ObjType) as IOneVariableFunction;
                }

                return func;
            }
            else throw new Exception(results.Errors[0].ToString());
        }
    }
}